#include "tlvsolvers.h"

void RegisterSolvers(){
    static bool haveRegister = false;
    if(haveRegister)return;
    //qRegisterMetaType<TlvSolver0x161>();
    haveRegister = true;
}

void TlvSolver0x161::unpack()
{
    skipBytes(2);
    readTLVS(tlvs);
    //RunTlvSolvers(tlvs);
    //i dont want to see the shit reflection with cpp
    if(tlvs.contains(0x172))rollbackSig = tlvs[0x172];
    if(tlvs.contains(0x173))tlvSolver0x173.setData(tlvs[0x173]).unpack();
    if(tlvs.contains(0x17f))tlvSolver0x17f.setData(tlvs[0x17f]).unpack();
}

void RunTlvSolvers(QMap<short, QVariant> &tlvs)
{
    abort();//dont call this shit function
    //mother fucker.
    foreach (short key, tlvs.keys()) {
        QByteArray className = "TlvSolver0x"+QString::number(key,16).toLatin1();
        int id = QMetaType::type(className);
        if(id != 0){
            TlvSolver *tmp = (TlvSolver*)QMetaType::create(id);
            tmp->setData(tlvs[key].value<QByteArray>()).unpack();
            tlvs[key] = QVariant::fromValue((void*)tmp);
            //emmm...we can't gen it's base class's meta data.so cast it.
            //i don't know whether it can be released truely
            qDebug()<<"Parse Solvers Success"<<className;
        }else qDebug()<<"Unknown Solvers"<<className;
    }
}

void TlvSolver0x173::unpack()
{
    readByte(type);
    readBytes(host,LengthType::SHORT);
    readShort(port);
}

void TlvSolver0x17f::unpack()
{
    readByte(type);
    readBytes(host,LengthType::SHORT);
    readShort(port);
}

void TlvSolver0x119::unpack()
{
    skipBytes(2);
    readTLVS(tlvs);
    if(tlvs.contains(0x1c))abort();//what the fuck shit
    if(tlvs.contains(0x130))tlvSolver0x130.setData(tlvs[0x130]).unpack();
    if(tlvs.contains(0x113))tlvSolver0x113.setData(tlvs[0x113]).unpack();
    if(tlvs.contains(0x528)){}//raw data set to client
    if(tlvs.contains(0x530)){}//raw data set to client
    if(tlvs.contains(0x118))mainDisplayName = tlvs[0x118];
    if(tlvs.contains(0x108))ksid = tlvs[0x108];
    if(tlvs.contains(0x125))tlvSolver0x125.setData(tlvs[0x125]).unpack();
    if(tlvs.contains(0x186))tlvSolver0x186.setData(tlvs[0x186]).unpack();
    if(tlvs.contains(0x537)){}// i dont care about the shit data
    if(tlvs.contains(0x169)){}//fast login i dont care
    if(tlvs.contains(0x167))tlvSolver0x167.setData(tlvs[0x167]).unpack();
    if(tlvs.contains(0x317))qrPushSig = tlvs[0x317];
    if(tlvs.contains(0x11a))tlvSolver0x11a.setData(tlvs[0x11a]).unpack();
    if(tlvs.contains(0x199))tlvSolver0x199.setData(tlvs[0x199]).unpack();
    if(tlvs.contains(0x200))tlvSolver0x200.setData(tlvs[0x200]).unpack();
    if(tlvs.contains(0x512))tlvSolver0x512.setData(tlvs[0x512]).unpack();
    if(tlvs.contains(0x531))tlvSolver0x531.setData(tlvs[0x531]).unpack();
    if(tlvs.contains(0x11f))tlvSolver0x11f.setData(tlvs[0x11f]).unpack();

    //they create in default
    //then we pack into a class for the user to call at once
    loginSigInfo.uin = tlvSolver0x113.uin;
    loginSigInfo.encryptA1 = tlvSolver0x531.a1;
    loginSigInfo.noPicSig = tlvSolver0x531.noPicSig;
    //loginSigInfo.G = QByteArray();
    //loginSigInfo.dpwd = QByteArray();
    loginSigInfo.randSeed = tlvs[0x403];
    loginSigInfo.simpleInfo.uin = loginSigInfo.uin;
    loginSigInfo.simpleInfo.face = tlvSolver0x11a.face;
    loginSigInfo.simpleInfo.age = tlvSolver0x11a.age;
    loginSigInfo.simpleInfo.gender = tlvSolver0x11a.gender;
    loginSigInfo.simpleInfo.nick = tlvSolver0x11a.nick;
    loginSigInfo.simpleInfo.imgType = tlvSolver0x167.imgType;
    loginSigInfo.simpleInfo.imgFormat = tlvSolver0x167.imgFormat;
    loginSigInfo.simpleInfo.imgUrl = tlvSolver0x167.imgUrl;
    loginSigInfo.simpleInfo.mainDisplayName = tlvs[0x118];
    loginSigInfo.appPri = tlvs.contains(0x11f)?tlvSolver0x11f.appPri:-1;//4294967295L
    loginSigInfo.a2ExpiryTime = Util::getUTCTime() + 2160000L;
    loginSigInfo.loginBitmap = 0;
    loginSigInfo.tgt = tlvs[0x10a];
    loginSigInfo.a2CreationTime = Util::getUTCTime();
    loginSigInfo.tgtKey = tlvs[0x10d];
    loginSigInfo.sKey = tlvs[0x120];
    loginSigInfo.userSig64 = tlvs[0x121];
    loginSigInfo.accessToken = tlvs[0x136];
    loginSigInfo.openId = tlvSolver0x125.openId;
    loginSigInfo.openKey = tlvSolver0x125.openKey;
    loginSigInfo.d2 = tlvs[0x143];
    loginSigInfo.d2Key = tlvs[0x305];
    loginSigInfo.sid = tlvs[0x164];
    loginSigInfo.aqSig = tlvs[0x171];
    loginSigInfo.psKeyMap = tlvSolver0x512.psKey;
    loginSigInfo.pt4TokenMap = tlvSolver0x512.pt4token;
    loginSigInfo.superKey = tlvs[0x16d];
    loginSigInfo.payToken = tlvSolver0x199.payToken;
    loginSigInfo.pf = tlvSolver0x200.pf;
    loginSigInfo.pfKey = tlvSolver0x200.pfKey;
    loginSigInfo.da2 = tlvs[0x203];
    loginSigInfo.wtSessionTicket = tlvs[0x133];
    loginSigInfo.wtSessionTicketKey = tlvs[0x134];
    loginSigInfo.deviceToken = tlvs[0x322];
    loginSigInfo.vKey = tlvs[0x136];
    loginSigInfo.userStWebSig = tlvs[0x103];
    loginSigInfo.userStSig = tlvs[0x114];
    loginSigInfo.userStKey = tlvs[0x10e];
    loginSigInfo.lsKey = tlvs[0x11c];
    loginSigInfo.userA5 = tlvs[0x10b];
    loginSigInfo.userA8 = tlvs[0x102];
}

QByteArray TlvSolver0x119::getKey()
{
    return QQDeviceConfig::getInstance().tgtgKey;
}

void TlvSolver0x130::unpack()
{
    skipBytes(2);
    readInt(serverTime);
    readRaw(ipFromT149,4);
}

void TlvSolver0x113::unpack()
{
    readInt(uin);
}

void TlvSolver0x125::unpack()
{
    if(getUnReadSize() > 0){
        readBytes(openId,LengthType::SHORT);
        readBytes(openKey,LengthType::SHORT);
    }
}

void TlvSolver0x186::unpack()
{
    skipBytes(1);
    readByte(pwdFlag);
}

void TlvSolver0x167::unpack()
{
    readByte(imgType);
    readByte(imgFormat);
    readBytes(imgUrl,LengthType::SHORT);
}

void TlvSolver0x11a::unpack()
{
    if(getUnReadSize() > 0){
        readShort(face);
        readByte(age);
        readByte(gender);
        readBytes(nick,LengthType::BYTE);
    }
}

void TlvSolver0x199::unpack()
{
    readBytes(openId,LengthType::SHORT);
    readBytes(payToken,LengthType::SHORT);
}

void TlvSolver0x200::unpack()
{
    if(getUnReadSize() > 0){
        readBytes(pf,LengthType::SHORT);
        readBytes(pfKey,LengthType::SHORT);
    }
}

void TlvSolver0x512::unpack()
{
    if(getUnReadSize() == 0)abort();//fuck
    short count;
    readShort(count);
    for(int i=0;i<count;++i){
        QByteArray domain;
        QByteArray m_pskey;
        QByteArray m_pt4token;
        readBytes(domain,LengthType::SHORT).readBytes(m_pskey,LengthType::SHORT).readBytes(m_pt4token,LengthType::SHORT);
        if(m_pskey.size() > 0)psKey[domain] = m_pskey;
        if(m_pt4token.size() > 0)pt4token[domain] = m_pt4token;
    }
}

void TlvSolver0x531::unpack()
{
    readTLVS(tlvs);
    a1 = tlvs[0x106] + tlvs[0x10c];
    noPicSig = tlvs[0x16a];
}

void TlvSolver0x11f::unpack()
{
    skipBytes(4);
    readInt(appPri);
}

void TlvSolver0x204::unpack()
{

}
